/*
 * Middleware
 * Copyright (C) 2010/11
 * Marco Buzzanca, Davide Giuseppe Monaco, Riccardo Pulvirenti, Giuseppe Ravidà,
 * Andrea Tino
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANDABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program. If not, see http://www.gnu.org/licenses
 */

/*!
 * File: xml_syn_logging.hpp
 */

#ifndef _XML_SYN_LOGGING_HPP_
#define _XML_SYN_LOGGING_HPP_

#include <iostream>
#include <fstream>
#include <string>
#include <boost/thread/mutex.hpp>
#include <boost/thread.hpp>
#include <boost/bind.hpp>
#include <boost/date_time/posix_time/posix_time.hpp>
#include <boost/date_time/local_time/local_time.hpp>
#include <boost/lexical_cast.hpp>
#include <xercesc/dom/DOMImplementation.hpp>
#include <xercesc/dom/DOMImplementationLS.hpp>
#include <xercesc/dom/DOMImplementationRegistry.hpp>
#include <xercesc/dom/DOMLSParser.hpp>
#include <xercesc/dom/DOMLSSerializer.hpp>
#include <xercesc/dom/DOMElement.hpp>
#include <xercesc/dom/DOMDocument.hpp>
#include <xercesc/util/PlatformUtils.hpp>
#include <xercesc/util/XMLString.hpp>
#include <xercesc/parsers/XercesDOMParser.hpp>
#include <xercesc/framework/MemBufInputSource.hpp>

#include "address.hpp"
#include "task_descriptor.hpp"
#include "worker_descriptor.hpp"
#include "workflow.hpp"
#include "file_cta_proxy.hpp"

#define PRINT_LOG_TO_WRITE

//-----------------------------------------------------------------------------
// Constants
namespace middleware {
namespace logging {
/*!
 * Enumerator for file open mode.
 */
typedef enum {
	/*!
	 * When constructing an XmlSynLogger object, passing this flag, the
	 * log file, at initialization time, if another file named the same is
	 * present, will be open in appending mode.
	 */
	kLogOpenKeepFile = 0,
	/*!
	 * When constructing an XmlSynLogger object, passing this flag, the
	 * log file, at initialization time, if another file named the same is
	 * present, will be open in overwrite mode.
	 */
	kLogOpenOverwriteFile = 1
} XmlSynLoggerOpenMode;
/*!
 * Enumerator for xml composition mode
 */
typedef enum {
	/*!
	 * Creates a normal xml with nothind added.
	 */
	kNormal = 0,
	/*!
	 * Adds a transformation schema.
	 */
	kAddXsl = 1
} XmlSynLoggerCompositionMode;
/*!
 * Enumerator for timestamp date and time settings.
 */
typedef enum {
	/*!
	 * Time is printed using local time.
	 */
	kUseLocalTime = 0,
	/*!
	 * Use universal time.
	 */
	kUseUniversalTime = 1
} XmlSynLoggerTimestampMode;
/*!
 * Etiquette for output.
 */
const std::string kXmlSynLoggerEtq = "XmlSynLogger";
/*!
 * How much to wait to write log
 */
const unsigned int kLogWriterWritePeriodMsec = 5000;
/*!
 * Default transform stylesheet.
 */
const std::string kLogDefXslStylesheet = "middleware_xslt.xsl";
/*!
 * All tags
 */
const std::string kTimestampLogTagParameter = "timestamp";
const std::string kIssuerLogTagParameter = "issuer";
const std::string kEventLogTag = "Event";
const std::string kEventsLogTag = "Events";
const std::string kErrorLogTag = "Error";
const std::string kWorkflowSubmittedEventLogTag = "WorkflowSubmitted";
const std::string kWorkflowEnqueuedEventLogTag = "WorkflowEnqueued";
const std::string kWorkflowDequeuedEventLogTag = "WorkflowDequeued";
const std::string kTaskSentEventLogTag = "TaskSent";
const std::string kTaskReceivedEventLogTag = "TaskReceived";
const std::string kWorkerDescriptorAddedEventLogTag = "WorkerDescriptorAdded";
const std::string kWorkerDescriptorUpdatedEventLogTag = "WorkerDescriptorUpdated";
const std::string kTaskEnqueuedEventLogTag = "TaskEnqueued";
const std::string kTaskDequeuedEventLogTag = "TaskDequeued";
const std::string kStatusUpdateLoopEventLogTag = "StatusUpdateLoop";
const std::string kTDCCollectorLoopExecEventLogTag = "TDCCollectorLoopExec";
const std::string kExecTaskStillNotExecutedEventLogTag = "ExecTaskStillNotExecuted";
const std::string kTaskExecutedEventLogTag = "TaskExecuted";
const std::string kWorkerDescriptorSentEventLogTag = "WorkerDescriptorSent";
} /* logging */
} /* middleware */
//-----------------------------------------------------------------------------
// Class definitions
namespace middleware {
namespace logging {
// Forward declarations
class Event;
class Error;
class WorkflowSubmitted;
class WorkflowEnqueued;
class WorkflowDequeued;
class TaskSent;
class TaskReceived;
class WorkerDescriptorAdded;
class WorkerDescriptorUpdated;
class TaskEnqueued;
class TaskDequeued;
class StatusUpdateLoop;
class TDCCollectorLoopExec;
class ExecTaskStillNotExecuted;
class TaskExecuted;
class WorkerDescriptorSent;
/*----/-----/-----/-----/-----/-----/-----/-----/-----/-----/-----/-----/----*/
/*!
 * XmlSynLogger class
 */
class XmlSynLogger {
public:
	/*!
	 * Default constructor. It should not be used, parameters casually
	 * configured!
	 */
	XmlSynLogger();
	/*!
	 * Constructor, filename non extension, it is added in ctor.
	 */
	XmlSynLogger(std::string filename, std::string peer_id, CTAPort cta_port,
			XmlSynLoggerOpenMode open_mode = kLogOpenOverwriteFile,
			XmlSynLoggerCompositionMode comp_mode = kNormal);
	/*!
	 * Copy-constructor.
	 */
	XmlSynLogger(const XmlSynLogger& logger);
	/*!
	 * Destructor
	 */
	~XmlSynLogger();
	/*!
	 * Exposing the file mutex in order to let other processes to access the
	 * logfile in mutual exclusion concurrency.
	 */

	/*!
	 * To log
	 */
	XmlSynLogger& operator<<(const Event& e);
	XmlSynLogger& operator<<(const Error& e);
	XmlSynLogger& operator<<(const WorkflowSubmitted& e);
	XmlSynLogger& operator<<(const WorkflowEnqueued& e);
	XmlSynLogger& operator<<(const WorkflowDequeued& e);
	XmlSynLogger& operator<<(const TaskSent& e);
	XmlSynLogger& operator<<(const TaskReceived& e);
	XmlSynLogger& operator<<(const WorkerDescriptorAdded& e);
	XmlSynLogger& operator<<(const WorkerDescriptorUpdated& e);
	XmlSynLogger& operator<<(const TaskEnqueued& e);
	XmlSynLogger& operator<<(const TaskDequeued& e);
	XmlSynLogger& operator<<(const StatusUpdateLoop& e);
	XmlSynLogger& operator<<(const TDCCollectorLoopExec& e);
	XmlSynLogger& operator<<(const ExecTaskStillNotExecuted& e);
	XmlSynLogger& operator<<(const TaskExecuted& e);
	XmlSynLogger& operator<<(const WorkerDescriptorSent& e);
	/*!
	 * Returns the timestamp. "dd/mm/yyyy hh:mm:ss.xxxx"
	 */
	static std::string LogTimestamp(
			XmlSynLoggerTimestampMode mode = kUseUniversalTime);
private:
	/*!
	 * Initializes file creating it concordently to the chosen mode.
	 */
	void InitParser(XmlSynLoggerOpenMode open_mode,
			XmlSynLoggerCompositionMode comp_mode);
	/*!
	 * Gets an immediate reference to the Dom object from the parser.
	 */
	xercesc::DOMDocument* GetXmlDocument() {
		return this->_parser->getDocument();
	}
	/*!
	 * Gets an immediate reference to the Root element object from the document.
	 */
	xercesc::DOMElement* GetXmlDocumentRootElement() {
		xercesc::DOMDocument* xmldoc = this->GetXmlDocument();
		return xmldoc->getDocumentElement();
	}
	/*!
	 * Gets an immediate reference to the Events element object from the
	 * document where all events must be placed.
	 */
	xercesc::DOMElement* GetXmlEventsElement() {
		xercesc::DOMElement* root = this->GetXmlDocumentRootElement();
		xercesc::DOMElement* events =
				root->getFirstElementChild()->getNextElementSibling();
		return events;
	}
	/*!
	 * Runs one instance of the thread to write the log file.
	 */
	void RunLogFileWriter() {
		this->_logfile_writer_thread.reset();
		this->_logfile_writer_thread = boost::shared_ptr<boost::thread>(
				new boost::thread(
						boost::bind(&XmlSynLogger::Exec_LogFileWriter, this)));
	}
	/*!
	 * Execution flow for the writer thread.
	 */
	void Exec_LogFileWriter();
	/*!
	 * Writes, periodically, the logfile
	 */
	boost::shared_ptr<boost::thread> _logfile_writer_thread;
	/*!
	 * DOM tree for log
	 */
	xercesc::XercesDOMParser* _parser;
	/*!
	 * Concurrence manager: mutex for dom. It guards the dom object and it is
	 * locked when the dom is read and written.
	 */
	boost::mutex _log_dom_monitor;
	/*!
	 * Port where bind the CTA protocol.
	 */
	CTAPort _log_cta_port;
	/*!
	 * File name (xml), complete name filename.ext
	 */
	std::string _log_filename;
	/*!
	 * Peer identifier for the log
	 */
	std::string _peer_identifier;
}; /* XmlSynLogger */
/*----/-----/-----/-----/-----/-----/-----/-----/-----/-----/-----/-----/----*/
/*!
 * Event represents the generic event worth of logging.
 * Discovery, Manager, UI and Worker, however, have a set of canonical triggered
 * events directly mapped on an Event child class.
 */
class Event {
	/*!
	* Current Event's brief description.
	*/
	std::string _body;
protected:
	/*!
	* Current Event's issuer module (Discovery DISC, Manager MAN,
	* UI UI, Worker W).
	*/
	std::string _issuer;
	/*!
	* Current Event's Date and Time.
	*/
	std::string _timestamp;
public:
	/*!
	* @note This should not be used, use Event(timestamp, issuer) instead.
	*/
	Event(void);
	/*!
	* @param issuer     String containing issuer module of the Event (ie. UI, MAN).
	*/
	Event(std::string issuer);
	/*!
	* @param issuer     String containing issuer module of the Event (ie. UI, MAN).
	* @param body       String containing a brief Event description.
	*/
	Event(std::string issuer, std::string body);
	/*!
	* Destructor
	*/
	virtual ~Event(void);
	/*!
	*
	*/
	void SetBody(std::string body)
		{ _body = body; }
	/*!
	*
	*/
	std::string GetBody(void) const
		{ return _body; }
	/*!
	*
	*/
	void SetIssuer(std::string issuer)
		{ _issuer = issuer; }
	/*!
	*
	*/
	std::string GetIssuer(void) const
		{ return _issuer; }
	/*!
	*
	*/
	void SetTimestamp(std::string timestamp)
		{ _timestamp = timestamp; }
	/*!
	*
	*/
	std::string GetTimestamp(void) const
		{ return _timestamp; }
	/*!
	 * XmlSynLogger::operator <<() MUST be friend to access private
	 * class section in order to produce XML Logging.
	 */
	friend XmlSynLogger& XmlSynLogger::operator<<(const Event& e);
}; /* Event */
/*----/-----/-----/-----/-----/-----/-----/-----/-----/-----/-----/-----/----*/
/*!
 * Error represents a generic error in the application.
 */
class Error : public Event {
protected:
	/*!
	* Error causes and description.
	*/
	std::string _description;
public:
	/*!
	* @note This should not be used, use Event(timestamp, issuer) instead.
	*/
	Error(void);
	/*!
	* @param issuer     String containing issuer module of the Event (ie. UI, MAN).
	*/
	Error(std::string issuer);
	/*!
	* @param issuer     String containing issuer module of the Event (ie. UI, MAN).
	* @param desc       String containing a brief error description.
	*/
	Error(std::string desc, std::string issuer = std::string(""));
	/*!
	* Destructor
	*/
	virtual ~Error(void);
	/*!
	*
	*/
	void SetDescription(std::string desc)
		{ _description = desc; }
	/*!
	*
	*/
	std::string GetDescription(void) const
		{ return _description; }
	/*!
	 * XmlSynLogger::operator <<() MUST be friend to access private
	 * class section in order to produce XML Logging.
	 */
	friend XmlSynLogger& XmlSynLogger::operator<<(const Error& e);
}; /* Event */
/*----/-----/-----/-----/-----/-----/-----/-----/-----/-----/-----/-----/----*/
/*!
 * WorkflowSubmitted represents the event triggered by UI module when a
 * new Workflow is sent to Manager.
 */
class WorkflowSubmitted : public Event {
protected:
	/*!
	*
	*/
	Workflow* _workflow;
public:
	/*!
	*
	*/
	WorkflowSubmitted(void);
	/*!
	*
	*/
	WorkflowSubmitted(std::string issuer = std::string("UI"));
	/*!
	*
	*/
	WorkflowSubmitted(Workflow* workflow,
			std::string issuer = std::string("UI"));
	/*!
	*
	*/
	virtual ~WorkflowSubmitted(void);
	/*!
	*
	*/
	void SetWorkflow(Workflow* workflow)
		{ _workflow = workflow; }
	/*!
	*
	*/
	Workflow* GetWorkflow(void) const
		{ return _workflow; }
	/*!
	 * XmlSynLogger::operator <<() MUST be friend to access private
	 * class section in order to produce XML Logging.
	 */
	friend XmlSynLogger& XmlSynLogger::operator<<(const WorkflowSubmitted& e);
}; /* WorkflowSubmitted */
/*----/-----/-----/-----/-----/-----/-----/-----/-----/-----/-----/-----/----*/
/*!
 * WorkflowEnqueued represents the event triggered by Manager module when a new Workflow
 * is enqueued into its Container.
 */
class WorkflowEnqueued : public Event {
protected:
	/*!
	*
	*/
	Workflow* _workflow;
public:
	/*!
	*
	*/
	WorkflowEnqueued(void);
	/*!
	*
	*/
	WorkflowEnqueued(std::string issuer = std::string("MAN"));
	/*!
	*
	*/
	WorkflowEnqueued(Workflow* workflow,
			std::string issuer = std::string("MAN"));
	/*!
	*
	*/
	virtual ~WorkflowEnqueued(void);
	/*!
	*
	*/
	void SetWorkflow(Workflow* workflow)
		{ _workflow = workflow; }
	/*!
	*
	*/
	Workflow* GetWorkflow(void) const
		{ return _workflow; }
	/*!
	 * XmlSynLogger::operator <<() MUST be friend to access private
	 * class section in order to produce XML Logging.
	 */
	friend XmlSynLogger& XmlSynLogger::operator<<(const WorkflowEnqueued& e);
}; /* WorkflowEnqueued */
/*----/-----/-----/-----/-----/-----/-----/-----/-----/-----/-----/-----/----*/
/*!
 * WorkflowDequeued represents the event triggered by Manager module when a
 * new Workflow is popped from its Container.
 */
class WorkflowDequeued : public Event {
protected:
	/*!
	*
	*/
	Workflow* _workflow;
public:
	/*!
	*
	*/
	WorkflowDequeued(void);
	/*!
	*
	*/
	WorkflowDequeued(std::string issuer = std::string("MAN"));
	/*!
	*
	*/
	WorkflowDequeued(Workflow* workflow,
			std::string issuer = std::string("MAN"));
	/*!
	*
	*/
	virtual ~WorkflowDequeued(void);
	/*!
	*
	*/
	void SetWorkflow(Workflow* workflow)
		{ _workflow = workflow; }
	/*!
	*
	*/
	Workflow* GetWorkflow(void) const
		{ return _workflow; }
	/*!
	 * XmlSynLogger::operator <<() MUST be friend to access private
	 * class section in order to produce XML Logging.
	 */
	friend XmlSynLogger& XmlSynLogger::operator<<(const WorkflowDequeued& e);
}; /* WorkflowDequeued */
/*----/-----/-----/-----/-----/-----/-----/-----/-----/-----/-----/-----/----*/
/*!
 * TaskSent represents the event triggered by Manager module when a TaskDescriptor
 * is sent to another Manager for execution.
 */
class TaskSent : public Event {
protected:
	/*!
	*
	*/
	TaskDescriptor* _task_descriptor;
	/*!
	*
	*/
	Address* _addr;
public:
	/*!
	*
	*/
	TaskSent(void);
	/*!
	*
	*/
	TaskSent(std::string issuer = std::string("MAN"));
	/*!
	*
	*/
	TaskSent(TaskDescriptor* task_descriptor, Address* addr,
			std::string issuer = std::string("MAN"));
	/*!
	*
	*/
	virtual ~TaskSent(void);
	/*!
	*
	*/
	void SetTaskDescriptor(TaskDescriptor* task_descriptor)
		{ _task_descriptor = task_descriptor; }
	/*!
	*
	*/
	TaskDescriptor* GetTaskDescriptor(void) const
		{ return _task_descriptor; }
	/*!
	*
	*/
	void SetAddress(Address* addr)
		{ _addr = addr; }
	/*!
	*
	*/
	Address* GetAddress(void) const
		{ return _addr; }
	/*!
	 * XmlSynLogger::operator <<() MUST be friend to access private
	 * class section in order to produce XML Logging.
	 */
	friend XmlSynLogger& XmlSynLogger::operator<<(const TaskSent& e);
}; /* TaskSent */
/*----/-----/-----/-----/-----/-----/-----/-----/-----/-----/-----/-----/----*/
/*!
 * TaskReceived represents the event triggered by Manager module when a
 * TaskDescriptor is received from another Manager for execution.
 */
class TaskReceived : public Event {
protected:
	/*!
	*
	*/
	TaskDescriptor* _task_descriptor;
	/*!
	*
	*/
	Address* _addr;
public:
	/*!
	*
	*/
	TaskReceived(void);
	/*!
	*
	*/
	TaskReceived(std::string issuer = std::string("MAN"));
	/*!
	*
	*/
	TaskReceived(TaskDescriptor* task_descriptor, Address* addr,
			std::string issuer = std::string("MAN"));
	/*!
	*
	*/
	virtual ~TaskReceived(void);
	/*!
	*
	*/
	void SetTaskDescriptor(TaskDescriptor* task_descriptor)
		{ _task_descriptor = task_descriptor; }
	/*!
	*
	*/
	TaskDescriptor* GetTaskDescriptor(void) const
		{ return _task_descriptor; }
	/*!
	*
	*/
	void SetAddress(Address* addr)
		{ _addr = addr; }
	/*!
	*
	*/
	Address* GetAddress(void) const
		{ return _addr; }
	/*!
	 * XmlSynLogger::operator <<() MUST be friend to access private
	 * class section in order to produce XML Logging.
	 */
	friend XmlSynLogger& XmlSynLogger::operator<<(const TaskReceived& e);
}; /* TaskReceived */
/*----/-----/-----/-----/-----/-----/-----/-----/-----/-----/-----/-----/----*/
/*!
 * WorkerDescriptorAdded represents the event triggered by Discovery module
 * when a WorkerDescriptor is received from a Worker for registration.
 */
class WorkerDescriptorAdded : public Event {
protected:
	/*!
	*
	*/
	WorkerDescriptor* _worker_descriptor;
	/*!
	*
	*/
	Address* _addr;
public:
	/*!
	*
	*/
	WorkerDescriptorAdded(void);
	/*!
	*
	*/
	WorkerDescriptorAdded(std::string issuer = std::string("DISC"));
	/*!
	*
	*/
	WorkerDescriptorAdded(WorkerDescriptor* worker_descriptor, Address* addr,
			std::string issuer = std::string("DISC"));
	/*!
	*
	*/
	virtual ~WorkerDescriptorAdded(void);
	/*!
	*
	*/
	void SetWorkerDescriptor(WorkerDescriptor* worker_descriptor)
		{ _worker_descriptor = worker_descriptor; }
	/*!
	*
	*/
	WorkerDescriptor* GetWorkerDescriptor(void) const
		{ return _worker_descriptor; }
	/*!
	*
	*/
	void SetAddress(Address* addr)
		{ _addr = addr; }
	/*!
	*
	*/
	Address* GetAddress(void) const
		{ return _addr; }
	/*!
	 * XmlSynLogger::operator <<() MUST be friend to access private
	 * class section in order to produce XML Logging.
	 */
	friend XmlSynLogger& XmlSynLogger::operator<<(const WorkerDescriptorAdded& e);
}; /* WorkerDescriptorAdded */
/*----/-----/-----/-----/-----/-----/-----/-----/-----/-----/-----/-----/----*/
/*!
 * WorkerDescriptorUpdated represents the event triggered by Discovery module when a
 * WorkerDescriptor is received from a Worker for status updating.
 */
class WorkerDescriptorUpdated : public Event {
protected:
	/*!
	*
	*/
	WorkerDescriptor* _worker_descriptor;
	/*!
	*
	*/
	Address* _addr;
public:
	/*!
	*
	*/
	WorkerDescriptorUpdated(void);
	/*!
	*
	*/
	WorkerDescriptorUpdated(std::string issuer = std::string("DISC"));
	/*!
	*
	*/
	WorkerDescriptorUpdated(WorkerDescriptor* worker_descriptor,
			Address* addr, std::string issuer = std::string("DISC"));
	/*!
	*
	*/
	virtual ~WorkerDescriptorUpdated(void);
	/*!
	*
	*/
	void SetWorkerDescriptor(WorkerDescriptor* worker_descriptor)
		{ _worker_descriptor = worker_descriptor; }
	/*!
	*
	*/
	WorkerDescriptor* GetWorkerDescriptor(void) const
		{ return _worker_descriptor; }
	/*!
	*
	*/
	void SetAddress(Address* addr)
		{ _addr = addr; }
	/*!
	*
	*/
	Address* GetAddress(void) const
		{ return _addr; }
  /*!
   * XmlSynLogger::operator <<() MUST be friend to access private
   * class section in order to produce XML Logging.
   */
  friend XmlSynLogger& XmlSynLogger::operator<<(const WorkerDescriptorUpdated& e);
}; /* WorkerDescriptorUpdated */
/*----/-----/-----/-----/-----/-----/-----/-----/-----/-----/-----/-----/----*/
/*!
 * TaskEnqueued represents the event triggered by Worker module when a TaskDescriptor
 * is pushed into its Container.
 */
class TaskEnqueued : public Event {
protected:
	/*!
	*
	*/
	TaskDescriptor* _task_descriptor;
public:
	/*!
	*
	*/
	TaskEnqueued(void);
	/*!
	*
	*/
	TaskEnqueued(std::string issuer = std::string("W"));
	/*!
	*
	*/
	TaskEnqueued(TaskDescriptor* task_descriptor,
			std::string issuer = std::string("W"));
	/*!
	*
	*/
	virtual ~TaskEnqueued(void);
	/*!
	*
	*/
	void SetTaskDescriptor(TaskDescriptor* task_descriptor)
		{ _task_descriptor = task_descriptor; }
	/*!
	*
	*/
	TaskDescriptor* GetTaskDescriptor(void) const
		{ return _task_descriptor; }
  /*!
   * XmlSynLogger::operator <<() MUST be friend to access private
   * class section in order to produce XML Logging.
   */
  friend XmlSynLogger& XmlSynLogger::operator<<(const TaskEnqueued& e);
}; /* TaskEnqueued */
/*----/-----/-----/-----/-----/-----/-----/-----/-----/-----/-----/-----/----*/
/*!
 * TaskDequeued represents the event triggered by Worker module when a TaskDescriptor
 * is popped out from its Container.
 */
class TaskDequeued : public Event {
protected:
	/*!
	*
	*/
	TaskDescriptor* _task_descriptor;
public:
	/*!
	*
	*/
	TaskDequeued(void);
	/*!
	*
	*/
	TaskDequeued(std::string issuer = std::string("W"));
	/*!
	*
	*/
	TaskDequeued(TaskDescriptor* task_descriptor,
			std::string issuer = std::string("W"));
	/*!
	*
	*/
	virtual ~TaskDequeued(void);
	/*!
	*
	*/
	void SetTaskDescriptor(TaskDescriptor* task_descriptor)
		{ _task_descriptor = task_descriptor; }
	/*!
	*
	*/
	TaskDescriptor* GetTaskDescriptor(void) const
		{ return _task_descriptor; }
  /*!
   * XmlSynLogger::operator <<() MUST be friend to access private
   * class section in order to produce XML Logging.
   */
  friend XmlSynLogger& XmlSynLogger::operator<<(const TaskDequeued& e);
}; /* TaskDequeued */
/*----/-----/-----/-----/-----/-----/-----/-----/-----/-----/-----/-----/----*/
/*!
 * StatusUpdateLoop represents the event triggered by Worker module when its
 * WorkerDescriptor is being updated.
 */
class StatusUpdateLoop : public Event {
protected:
	/*!
	*
	*/
	WorkerDescriptor* _worker_descriptor;
	/*!
	*
	*/
	WorkerDescriptor* _old_worker_descriptor;
	/*!
	*
	*/
	bool _status_changed;
public:
	/*!
	*
	*/
	StatusUpdateLoop(void);
	/*!
	*
	*/
	StatusUpdateLoop(std::string issuer = std::string("W"));
	/*!
	*
	*/
	StatusUpdateLoop(bool status_changed, WorkerDescriptor* worker_descriptor,
			WorkerDescriptor* old_worker_descriptor,
			std::string issuer = std::string("W"));
	/*!
	*
	*/
	virtual ~StatusUpdateLoop(void);
	/*!
	*
	*/
	void SetWorkerDescriptor(WorkerDescriptor* worker_descriptor)
		{ _worker_descriptor = worker_descriptor; }
	/*!
	*
	*/
	WorkerDescriptor* GetWorkerDescriptor(void) const
		{ return _worker_descriptor; }
	/*!
	*
	*/
	void SetOldWorkerDescriptor(WorkerDescriptor* old_worker_descriptor)
		{ _old_worker_descriptor = old_worker_descriptor; }
	/*!
	*
	*/
	WorkerDescriptor* GetOldWorkerDescriptor(void) const
		{ return _old_worker_descriptor; }
	/*!
	*
	*/
	void SetStatusChanged(bool status_changed)
		{ _status_changed = status_changed; }
	/*!
	*
	*/
	bool IsStatusChanged(void) const
		{ return _status_changed; }
  /*!
   * XmlSynLogger::operator <<() MUST be friend to access private
   * class section in order to produce XML Logging.
   */
  friend XmlSynLogger& XmlSynLogger::operator<<(const StatusUpdateLoop& e);
};
/*----/-----/-----/-----/-----/-----/-----/-----/-----/-----/-----/-----/----*/
/*!
 * TDCCollectorLoopExec represents the event triggered by Worker module when
 * the TDC garbage loop ends one execution. */
class TDCCollectorLoopExec : public Event {
protected:
	/*!
	*
	*/
	unsigned int _collected;
public:
	/*!
	*
	*/
	TDCCollectorLoopExec(void);
	/*!
	*
	*/
	TDCCollectorLoopExec(std::string issuer = std::string("W"));
	/*!
	*
	*/
	TDCCollectorLoopExec(unsigned int collected,
			std::string issuer = std::string("W"));
	/*!
	*
	*/
	virtual ~TDCCollectorLoopExec(void);
	/*!
	*
	*/
	void SetCollected(unsigned int collected)
		{ _collected = collected; }
	/*!
	*
	*/
	unsigned int GetCollected(void) const
		{ return _collected; }
  /*!
   * XmlSynLogger::operator <<() MUST be friend to access private
   * class section in order to produce XML Logging.
   */
  friend XmlSynLogger& XmlSynLogger::operator<<(const TDCCollectorLoopExec& e);
}; /* TDCCollectorLoopExec */
/*----/-----/-----/-----/-----/-----/-----/-----/-----/-----/-----/-----/----*/
/*!
 * ExecTaskStillNotExecuted represents the event triggered by Worker module when a
 * TaskDescriptor with Type 'Executable' is not executed for some reason.
 * The current attempt and maximum number of attempts are either logged.
 */
class ExecTaskStillNotExecuted : public Event {
protected:
	/*!
	*
	*/
	TaskDescriptor* _task_descriptor;
	/*!
	*
	*/
	unsigned int _attempt;
	/*!
	*
	*/
	unsigned int _attempts;
public:
	/*!
	*
	*/
	ExecTaskStillNotExecuted(void);
	/*!
	*
	*/
	ExecTaskStillNotExecuted(std::string issuer = std::string("W"));
	/*!
	*
	*/
	ExecTaskStillNotExecuted(TaskDescriptor* task_descriptor,
			unsigned int attempt, unsigned int attempts,
			std::string issuer = std::string("W"));
	/*!
	*
	*/
	virtual ~ExecTaskStillNotExecuted(void);
	/*!
	*
	*/
	void SetTaskDescriptor(TaskDescriptor* task_descriptor)
		{ _task_descriptor = task_descriptor; }
	/*!
	*
	*/
	TaskDescriptor* GetTaskDescriptor(void) const
		{ return _task_descriptor; }
	/*!
	*
	*/
	void SetAttempt(unsigned int attempt)
		{ _attempt = attempt; }
	/*!
	*
	*/
	unsigned int GetAttempt(void) const
		{ return _attempt; }
	/*!
	*
	*/
	void SetAttempts(unsigned int attempts)
		{ _attempts = attempts; }
	/*!
	*
	*/
	unsigned int GetAttempts(void) const
		{ return _attempts; }
  /*!
   * XmlSynLogger::operator <<() MUST be friend to access private
   * class section in order to produce XML Logging.
   */
  friend XmlSynLogger& XmlSynLogger::operator<<(const ExecTaskStillNotExecuted& e);
}; /* ExecTaskStillNotExecuted */
/*----/-----/-----/-----/-----/-----/-----/-----/-----/-----/-----/-----/----*/
/*!
 * TaskExecuted represents the event triggered by Worker module when the task specified in
 * TaskDescriptor is executed.
 */
class TaskExecuted : public Event {
protected:
	/*!
	*
	*/
	TaskDescriptor* _task_descriptor;
public:
	/*!
	*
	*/
	TaskExecuted(void);
	/*!
	*
	*/
	TaskExecuted(std::string issuer = std::string("W"));
	/*!
	*
	*/
	TaskExecuted(TaskDescriptor* task_descriptor,
			std::string issuer = std::string("W"));
	/*!
	*
	*/
	virtual ~TaskExecuted(void);
	/*!
	*
	*/
	void SetTaskDescriptor(TaskDescriptor* task_descriptor)
		{ _task_descriptor = task_descriptor; }
	/*!
	*
	*/
	TaskDescriptor* GetTaskDescriptor(void) const
		{ return _task_descriptor; }
  /*!
   * XmlSynLogger::operator <<() MUST be friend to access private
   * class section in order to produce XML Logging.
   */
  friend XmlSynLogger& XmlSynLogger::operator<<(const TaskExecuted& e);
}; /* TaskExecuted */
/*----/-----/-----/-----/-----/-----/-----/-----/-----/-----/-----/-----/----*/
/*!
 * WorkerDescriptorSent represents the event triggered by Discovery module when a
 * WorkerDescriptor is received from a Worker for registration.
 */
class WorkerDescriptorSent : public Event {
protected:
	/*!
	*
	*/
	WorkerDescriptor* _worker_descriptor;
	/*!
	*
	*/
	Address* _addr;
public:
	/*!
	*
	*/
	WorkerDescriptorSent(void);
	/*!
	*
	*/
	WorkerDescriptorSent(std::string issuer = std::string("W"));
	/*!
	*
	*/
	WorkerDescriptorSent(WorkerDescriptor* worker_descriptor, Address* addr,
			std::string issuer = std::string("W"));
	/*!
	*
	*/
	virtual ~WorkerDescriptorSent(void);
	/*!
	*
	*/
	void SetWorkerDescriptor(WorkerDescriptor* worker_descriptor)
		{ _worker_descriptor = worker_descriptor; }
	/*!
	*
	*/
	WorkerDescriptor* GetWorkerDescriptor(void) const
		{ return _worker_descriptor; }
	/*!
	*
	*/
	void SetAddress(Address* addr)
		{ _addr = addr; }
	/*!
	*
	*/
	Address* GetAddress(void) const
		{ return _addr; }
  /*!
   * XmlSynLogger::operator <<() MUST be friend to access private
   * class section in order to produce XML Logging.
   */
  friend XmlSynLogger& XmlSynLogger::operator<<(const WorkerDescriptorSent& e);
}; /* WorkerDescriptorSent */
} /* logging */
} /* middleware */

#endif
